package com.example.demo.pojo;

import lombok.Data;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
/**
 * @author luolinila
 */
@Data
public class Game implements Serializable {
    //玩家序列
    List<Player> players;
    //奖池
    double jackpot;
    //牌组
    PokerSet pokerSet;
    //公共牌
    List<Poker> communityPokers;
    //行动玩家下标
    int actionPlayer;
    //底注
    double ante;

    public Game() {
        this.players = new ArrayList<>();
        //清空奖池
        this.jackpot = 0;
        //洗牌
        this.pokerSet = new PokerSet();
        //清空公共牌
        this.communityPokers = new ArrayList<>();
        this.actionPlayer = 0;
        //底注为1
        this.ante = 1;
    }

    public Game(List<Player> players) {
        this.players = players;
        //清空奖池
        this.jackpot = 0;
        //洗牌
        this.pokerSet = new PokerSet();
        //清空公共牌
        this.communityPokers = new ArrayList<>();
        this.actionPlayer = 0;
        //底注为1
        this.ante = 1;
    }

    //发公共牌
    public void faPaiCommunity(int n) {
        communityPokers.addAll(pokerSet.faPai(n));
    }

    //发玩家手牌
    public void faPaiPlayersAll() {
        for (Player player : players) {
            //player.handPoker 为 List<Poker>
            //pokerSet.faPai 返回长度为 2 的 List<Poker>
            player.handPoker.addAll(this.pokerSet.faPai(2));
        }
    }

    //开牌
    public List<Integer> kaiPai() {
        //获取玩家序列手牌
        List<HandPoker> arr = new ArrayList<>();
        for (Player player : players) {
            arr.add(Poker.evaluateHand(player.getHandPoker(), this.communityPokers));
        }
        //获取赢家
        List<Integer> res = new ArrayList<>();
        int maxIndex = 0;
        for (int i = 0; i < arr.size(); i++) {
            //牌型更大时
            if (arr.get(maxIndex).compareTo(arr.get(i)) > 0) {
                //更新最大牌型
                maxIndex = i;
                //重置赢家序列
                res = new ArrayList<>();
                //加入赢家序列
                res.add(maxIndex);
            }
            //牌型相等时
            if (arr.get(maxIndex).compareTo(arr.get(i)) == 0) {
                //加入赢家序列
                res.add(i);
            }
        }
        return res;
    }

    //对局开始
    public void start() {
        //下小盲注
        players.get(players.size() - 1).add(this.ante / 2);
        //下大盲注
        players.get(players.size() - 2).add(this.ante);
        jackpot += ((double) 3 / 2) * ante;
    }

    //结束对局
    public void end() {
        //获取赢家序列
        List<Integer> res = kaiPai();
        //平分奖池
        double income = jackpot / res.size();
        //赢家序列对应下标增加
        for (Integer i: res) {
            players.get(i).chip += income;
        }
    }

    //获取行动玩家
    public Player getActionPlayer() {
        if (players.isEmpty()) {
            return null;
        }
        //actionPlayer 为玩家序列下标
        return players.get(actionPlayer);
    }

    //跟注
    public int call() {
        if (players.get(actionPlayer).add(ante) < 0) {
            return -1;
        }
        //跟注放入奖池
        jackpot += ante;
        System.out.println(jackpot + " " + ante);
        //行动玩家后移
        actionPlayer = (actionPlayer + 1) % players.size();
        //更新至 map
        //检验是否进入下一轮下注
        return isContinue();
    }

    //加注
    public int raise(double res) {
        if (res <= ante || players.get(actionPlayer).add(res) < 0) {
            return -1;
        }
        //跟注放入奖池
        jackpot += res;
        //更新底注
        this.ante = res;
        //行动玩家后移
        actionPlayer = (actionPlayer + 1) % players.size();
        //更新至 map
        //检验是否进入下一轮下注
        return isContinue();
    }

    //AllIn
    public int allIn() {
        double temp = players.get(actionPlayer).addAll();
        if (temp < 0) {
            return -1;
        }
        jackpot += temp;
        //AllIn之后所有玩家只能ALLIN
        this.ante = Integer.MAX_VALUE;
        //行动玩家后移
        actionPlayer = (actionPlayer + 1) % players.size();
        //检验是否进入下一轮下注
        return isContinue();
    }

    //弃牌
    public Player fold() {
        Player outPlayer = players.get(actionPlayer);
        //将弃牌玩家从玩家序列中移除
        players.remove(actionPlayer);
        //返回 players 长度
        return outPlayer;
    }

    //判断是否需要发下一轮的公共牌
    public int isContinue() {
        if (actionPlayer == 0) {
            switch (communityPokers.size()) {
                case 0: {
                    //发翻牌
                    faPaiCommunity(3);
                    break;
                }
                case 3: {
                    //发转牌
                    faPaiCommunity(1);
                    break;
                }
                case 4: {
                    //发河牌
                    faPaiCommunity(1);
                    break;
                }
                case 5: {
                    //结束对局
                    return 1;
                }
            }
        }
        return 0;
    }

}
